package Duoxiancheng;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Thread123_2 {
    static Lock lock = new ReentrantLock();
    static Condition condition1 = lock.newCondition();
    static Condition condition2 = lock.newCondition();
    static Condition condition3 = lock.newCondition();
    static AtomicInteger num = new AtomicInteger(0);
    public static void main(String[] args) {
        new Thread(new MineThread1()).start();
        new Thread(new MineThread2()).start();
        new Thread(new MineThread3()).start();
    }

    //可以发送，这样子写需要在最后unlock的时候也要signal后续的线程
    // 需要这么做是因为，在最后一轮的时候比如Thread1输出2然后唤醒了后续的线程，然后还是会再次进入while()循环，然后wait
    // 然后就算后面的num>超过了，其他线程都停了，因为thread1一直在阻塞着是不会停止的
    // 如果把while()改成for循环，那么最后一次是不会进入awati的，所以就不会最后一轮还会等待
    static class MineThread1 implements Runnable{
        @Override
        public void run() {
            try{
                lock.lock();

                while (num.get()<4){
                    System.out.println("A get lock");
                    if (num.get()%3==0){
                        System.out.println("1");
                        num.incrementAndGet();
                        System.out.println("signal Thread1");
                        condition2.signal();
                    }else {
                        System.out.println(Thread.currentThread().getName()+"wait");
                        condition1.await();
                    }
                }
            }catch (Exception e){

            }
            finally {
                System.out.println("A unlock");
                condition2.signal();
                lock.unlock();

            }

        }
    }

    static class MineThread2 implements Runnable{
        @Override
        public void run() {
            try{
                lock.lock();

                while (num.get()<4){
                    System.out.println("B get lock");
                    if (num.get()%3==1){
                        System.out.println("2");
                        num.incrementAndGet();
                        System.out.println("signal Thread2");
                        condition3.signal();
                    }else {
                        System.out.println(Thread.currentThread().getName()+"wait");
                        condition2.await();
                    }
                }
            }catch (Exception e){

            }
            finally {
                System.out.println("B unlock");
                condition3.signal();
                lock.unlock();
            }

        }
    }

    static class MineThread3 implements Runnable{
        @Override
        public void run() {
            try{
                lock.lock();

                while (num.get()<4){
                    System.out.println("C get lock");
                    if (num.get()%3==2){
                        System.out.println("3");
                        num.incrementAndGet();
                        System.out.println("signal Thread0");
                        condition1.signal();
                    }else {
                        System.out.println(Thread.currentThread().getName()+"wait");
                        condition3.await();
                    }
                }
            }catch (Exception e){

            }
            finally {
                System.out.println("C unlock");
                condition1.signal();
                lock.unlock();
            }

        }
    }


}
